//package com.kepler.social.domain.user.account;
//
//import com.kepler.social.app.port.UserLoginPort;
//import com.kepler.social.app.port.UserSecurityPort;
//import com.kepler.social.common.constants.BusinessState;
//import com.kepler.social.common.constants.Enums;
//import com.kepler.social.common.constants.RedisKeyConst;
//import com.kepler.social.common.constants.TipsConst;
//import com.kepler.social.common.exception.ServiceException;
//import com.kepler.social.common.exception.SystemException;
//import com.kepler.social.common.utils.DateTimeUtil;
//import com.kepler.social.common.utils.NickNameUtil;
//import com.kepler.social.common.utils.PasswordUtil;
//import com.kepler.social.common.utils.QxcUuid;
//import com.kepler.social.common.utils.RandomUtil;
//import com.kepler.social.common.utils.Safes;
//import com.kepler.social.common.utils.StringExtendsUtils;
//import com.kepler.social.common.utils.ValidateAssert;
//import com.kepler.social.core.sharding.DatasourceType;
//import com.kepler.social.domain.port.vo.UserMergeInfoVo;
//import com.kepler.social.domain.support.sms.SmsBo;
//import com.kepler.social.domain.user.account.consts.BusinessSeqEnum;
//import com.kepler.social.domain.user.account.consts.CommonConst;
//import com.kepler.social.domain.user.security.rules.MailRule;
//import com.kepler.social.common.rule.SmsRule;
//import com.kepler.social.generic.MailHelper;
//import com.kepler.social.generic.SeqHelper;
//import com.kepler.social.generic.SpringContextHelper;
//import com.kepler.social.user.dao.domain.UserInfo;
//import com.kepler.social.user.dao.domain.UserSocialInfo;
//import com.kepler.social.user.dao.mapper.UserInfoMapper;
//import com.kepler.social.user.dao.mapper.UserSocialInfoMapper;
//import com.kepler.social.usersecurity.dao.domain.UserEmail;
//import com.kepler.social.usersecurity.dao.domain.UserMobilePhone;
//import com.kepler.social.usersecurity.dao.domain.UserPassword;
//import com.kepler.social.usersecurity.dao.mapper.UserEmailMapper;
//import com.kepler.social.usersecurity.dao.mapper.UserMobilePhoneMapper;
//import com.kepler.social.usersecurity.dao.mapper.UserPasswordMapper;
//import jakarta.annotation.Resource;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//import org.apache.shardingsphere.infra.hint.HintManager;
//import org.redisson.api.RLock;
//import org.redisson.api.RedissonClient;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.security.crypto.password.PasswordEncoder;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;
//import org.thymeleaf.TemplateEngine;
//import org.thymeleaf.context.Context;
//
//import java.time.Duration;
//import java.time.LocalDateTime;
//import java.util.List;
//import java.util.Objects;
//import java.util.concurrent.TimeUnit;
//
///**
// * 用户账号相关服务
// * 相当于是一个子领域，根据领域的动作可以分为多个userCase, 如: UserLoginCase
// */
//@Service
//@Slf4j
//public class UserBoBak implements UserLoginPort, UserSecurityPort {
//
//    private static final Logger LOGGER = LoggerFactory.getLogger(UserBoBak.class);
//    @Value("${kepler.verif-mail-url}")
//    private String verifMailUrl;
//    @Resource
//    private MailHelper mailHelper;
//    @Resource
//    private SeqHelper seqHelper;
//    @Resource
//    private RedissonClient redissonClient;
//    /**
//     * 注意 用的是一套密码 如果变了 一定要改变
//     * kepler-social-web com.kepler.social.web.configuration.SecuritySubUnitConfig#passwordEncoder()
//     */
//    @Resource
//    private PasswordEncoder passwordEncoder;
//    @Resource
//    private RedisTemplate redisTemplate;
//    @Resource
//    private TemplateEngine templateEngine;
//    @Resource
//    private UserInfoMapper userInfoMapper;
//    @Resource
//    private UserSocialInfoMapper userSocialInfoMapper;
//    @Resource
//    private UserEmailMapper userEmailMapper;
//    @Resource
//    private UserMobilePhoneMapper userMobilePhoneMapper;
//    @Resource
//    private UserPasswordMapper userPasswordMapper;
//    @Resource
//    private SmsBo smsBo;
//
//    private final int passwordLength = 10;
//
//    /**
//     * @param email 电子邮件
//     * TODO 加入限流
//     */
//    @Override
//    public void sendVerifMail(String email){
//        ValidateAssert.isTrue(StringExtendsUtils.isEmail(email), TipsConst.incorrect_email_format);
//        UserEmail userEmail = userEmailMapper.selectByPrimaryKey(email);
//        ValidateAssert.notNull(userEmail, TipsConst.email_not_exists);
//        ValidateAssert.isTrue(Objects.isNull(userEmail)
//                        || userEmail.getState() != Enums.UserEmailStateEnum.USED.getCode(),
//                TipsConst.email_used);
//        ValidateAssert.isTrue(Objects.isNull(userEmail)
//                        || userEmail.getState() != Enums.UserEmailStateEnum.DISUSED.getCode(),
//                TipsConst.email_disused);
//        QxcUuid qxcUuid = QxcUuid.fastUUID();
//        LOGGER.info("verifMailSend  mail {} qxcUuid {}", email, qxcUuid);
//        redisTemplate.opsForValue().set(RedisKeyConst.EMAIL_VERIF_PREFIX + qxcUuid, email, CommonConst.expireTimeVerifMail, TimeUnit.SECONDS);
//        Context context = new Context();
//        context.setVariable("verifMailUrl",verifMailUrl);
//        context.setVariable("token",qxcUuid);
//        String mail = templateEngine.process("register_verif_mail_template.html", context);
//        mailHelper.sendHtmlMail(email, "注册验证邮件", mail);
//    }
//
//    /**
//     * 跨库事务:
//     *   用的是最终一致性方案
//     *   1、email
//     *        如果不存在，正在进行email和password的创建
//     *        如果状态未验证，拿出userId即可，因为这一个阶段成功了，说明后续操作失败，只需补操作哦
//     *        如果其他状态，那么表示已经被成功验证过了，不能再使用，即便这个邮箱账号被废弃了。
//     *   2、user
//     *        如果存在，什么操作都不用做，说明是后续操作失败，只需补操作即可
//     *        如果不存在，正常生成即可
//     *        失败没关系，用户再操作一次就可以
//     *   3、email
//     *        修改状态为使用中
//     *        失败没关系，用户再操作一次就可以
//     * @param token token
//     */
//    @Override
//    public void verifyVerifMail(String token) {
//        ValidateAssert.isTrue(StringUtils.isNoneBlank(token), TipsConst.email_verify_token_empty);
//        String email = (String) redisTemplate.opsForValue().get(RedisKeyConst.EMAIL_VERIF_PREFIX + token);
//        ValidateAssert.isTrue(StringUtils.isNotBlank(email), TipsConst.email_verify_token_expire);
//        // 分布式锁定
//        final RLock lock = redissonClient.getLock(RedisKeyConst.MAIL_LOCK_PREFIX + email);
//        try {
//            boolean res = lock.tryLock();
//            if (!res) {
//                throw new ServiceException(BusinessState.DUPLICATE_REQUESTS);
//            }
//            //保存邮件
//            Long userId = seqHelper.getSeqId(BusinessSeqEnum.USER.getBusinessName());
//            log.info("验证邮件成功 生成用户ID {} {}", email, userId);
//            //当前时间戳
//            long nowTime = DateTimeUtil.toMilli(LocalDateTime.now());
//            String password;
//            try (HintManager hintManager = HintManager.getInstance()) {
//                hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_USER_SECURITY.toString());
//                UserEmail userEmail = userEmailMapper.selectByPrimaryKey(email);
//                if (Objects.isNull(userEmail)) {
//                    // 因为要支持事务，否则只能另开一个类了。那样破坏了领域
//                    password = SpringContextHelper.getBean(UserBoBak.class).generateEmailAndPassword(email, userId,
//                            nowTime);
//                } else if (userEmail.getState() == Enums.UserEmailStateEnum.NOT_VERIFIED.getCode()) {
//                    userId = userEmail.getUserId();
//                    // 因为密码是摘要，无法逆运算，所以需要重新生成一次后更新
//                    this.resetPwd(userEmail.getUserId(), password = PasswordUtil.randomPassword(passwordLength));
//                } else {
//                    throw new ServiceException(TipsConst.email_used);
//                }
//            } catch (Exception e) {
//                log.error("生成邮件账号失败 email is {}  e is {}", email, e, e);
//                throw new SystemException("生成邮件账号失败");
//            }
//
//            try (HintManager hintManager = HintManager.getInstance()) {
//                hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_USER.toString());
//                SpringContextHelper.getBean(UserBoBak.class)
//                        .generateUserInfor(email, null, null, nowTime, userId);
//            } catch (Exception e) {
//                log.error("生成用户失败 email is {}  e is {}", email, e, e);
//                throw new SystemException("生成邮件账号失败");
//            }
//
//            try (HintManager hintManager = HintManager.getInstance()) {
//                hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_USER_SECURITY.toString());
//                UserEmail userEmail = userEmailMapper.selectByPrimaryKey(email);
//                userEmail.setState(Enums.UserEmailStateEnum.USED.getCode());
//                userEmailMapper.updateByPrimaryKey(userEmail);
//            } catch (Exception e) {
//                log.error("生成邮件账号失败 email is {}  e is {}", email, e, e);
//                throw new SystemException("请重新点击验证");
//            }
//
//            // 发送成功邮件 这个需要计入一个记录 以便错误之后进行重新发送
//            // 或者通过event的方式
//            Context context = new Context();
//            context.setVariable("userId", userId);
//            context.setVariable("accountType", "邮箱");
//            context.setVariable("account", email);
//            context.setVariable("password", password);
//            String mail = templateEngine.process("register_success_mail_template.html", context);
//            mailHelper.sendHtmlMail(email, "注册成功", mail);
//
//            //删除key,防止用户重复点击
//            redisTemplate.delete(RedisKeyConst.EMAIL_VERIF_PREFIX + token);
//        } finally {
//            if (null != lock && lock.isLocked()) { // 是否还是锁定状态
//                if (lock.isHeldByCurrentThread()) {//是否是当前执行线程的锁
//                    lock.unlock(); // 释放锁
//                }
//            }
//        }
//    }
//
//    @Transactional(rollbackFor = Exception.class)
//    public String generateEmailAndPassword(String email, Long userId, long nowTime) {
//        UserEmail userEmail = UserEmail.builder()
//                .email(email).userId(userId).createdTime(nowTime)
//                .modifiedTime(nowTime).disuseTime(0L).state(Enums.UserEmailStateEnum.NOT_VERIFIED.code)
//                .build();
//        userEmailMapper.insert(userEmail);
//        String password = PasswordUtil.randomPassword(passwordLength);
//        String encryptedPassword = passwordEncoder.encode(password);
//        UserPassword userPassword = UserPassword.builder()
//                .userId(userId).password(encryptedPassword).createdTime(nowTime).modifiedTime(nowTime)
//                .build();
//        userPasswordMapper.insert(userPassword);
//        return password;
//    }
//
//    @Override
//    public String findUserPassword(Long userId) {
//        UserPassword userPassword = userPasswordMapper.selectByPrimaryKey(userId);
//        ValidateAssert.notNull(userPassword, "无此用户!");
//        return userPassword.getPassword();
//    }
//
//    @Override
//    public Long findUserId(String email) {
//        UserEmail userEmail = userEmailMapper.selectByPrimaryKey(email);
//        ValidateAssert.notNull(userEmail,  TipsConst.email_not_exists);
//        ValidateAssert.isTrue(userEmail.getState() != Enums.UserEmailStateEnum.NOT_VERIFIED.getCode(),
//                TipsConst.email_to_be_verified);
//        ValidateAssert.isTrue(userEmail.getState() != Enums.UserEmailStateEnum.DISUSED.getCode(),
//                TipsConst.email_disused);
//        return userEmail.getUserId();
//    }
//
//    @Override
//    public void sendRetrievePasswordMobilePhoneCaptcha(Integer countryCallingCode, final Long mobilePhoneNumber) {
//        log.info("sendRetrievePasswordMobilePhoneCaptcha param phoneNumber {}", mobilePhoneNumber);
//        smsBo.sendMobilePhoneCaptcha(SmsRule.defaultCountryCallingCode(countryCallingCode),
//                mobilePhoneNumber, CommonConst.expireTimeCaptcha, TimeUnit.SECONDS,
//                () -> {
//                    UserMobilePhone phone = userMobilePhoneMapper.selectByState(
//                            SmsRule.defaultCountryCallingCode(countryCallingCode),
//                            mobilePhoneNumber,
//                            Enums.UserMobilePhoneStateEnum.USED.code);
//                    log.info("sendRetrievePasswordMobilePhoneCaptcha phoneNumber {} exists {}",
//                            mobilePhoneNumber, Objects.nonNull(phone));
//                    ValidateAssert.isTrue(Objects.nonNull(phone), TipsConst.mobile_phone_not_exists);
//                }
//        );
//    }
//
//    @Override
//    public void changePasswordByMobilePhone(Integer countryCallingCode, Long mobilePhoneNumber, Integer captcha, String password) {
//        ValidateAssert.isTrue(StringExtendsUtils.isMobilePhoneNumber(mobilePhoneNumber + ""), TipsConst.incorrect_mobile_phone_format);
//        ValidateAssert.notNull(captcha, TipsConst.captcha_missing);
//        countryCallingCode = SmsRule.defaultCountryCallingCode(countryCallingCode);
//        String lockKey = RedisKeyConst.PHONE_CAPTCHA_LOCK_PREFIX + mobilePhoneNumber;
//        final RLock lock = redissonClient.getLock(lockKey);
//        try {
//            boolean res = lock.tryLock();
//            if (!res) {
//                throw new ServiceException(BusinessState.DUPLICATE_REQUESTS);
//            }
//            // 校验验证码
//            smsBo.verifySmsCaptcha(countryCallingCode, mobilePhoneNumber, captcha, false);
//            // 查找手机账号
//            try (HintManager hintManager = HintManager.getInstance()) {
//                hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_USER_SECURITY.toString());
//                Long userId = this.findUserId(countryCallingCode, mobilePhoneNumber);
//                this.resetPwd(userId, password);
//            }
//            smsBo.sendPasswordChangeSuccessSms(countryCallingCode, mobilePhoneNumber, password, passwordEncoder.encode(password));
//        } finally {
//            if (null != lock && lock.isLocked()) { // 是否还是锁定状态
//                if (lock.isHeldByCurrentThread()) {//是否是当前执行线程的锁
//                    lock.unlock(); // 释放锁
//                }
//            }
//        }
//    }
//
//    @Override
//    public void sendRetrievePasswordEmailCaptcha(String email) {
//        ValidateAssert.isTrue(StringExtendsUtils.isEmail(email),TipsConst.incorrect_email_format);
//        int    captcha = RandomUtil.generateRandomNumber(4);
//        redisTemplate.opsForValue().set(RedisKeyConst.EMAIL_CAPTCHA_PREFIX + email, captcha,
//                CommonConst.expireTimeCaptcha, TimeUnit.SECONDS);
//        Context context = new Context();
//        context.setVariable("captcha",captcha);
//        String mail = templateEngine.process("captcha_mail_template.html", context);
//        mailHelper.sendHtmlMail(email, "验证码", mail);
//    }
//
//    @Override
//    public void changePasswordByEmail(String email, Integer captcha, String password) {
//        log.info("changePasswordByEmail email {} captcha {}", email, captcha);
//        ValidateAssert.isTrue(StringExtendsUtils.isEmail(email),TipsConst.incorrect_email_format);
//        ValidateAssert.isTrue(StringExtendsUtils.isNotBlank(password),TipsConst.empty_password);
//        ValidateAssert.notNull(captcha, TipsConst.captcha_missing);
//        Integer captchaCached = (Integer) redisTemplate.opsForValue().get(RedisKeyConst.EMAIL_CAPTCHA_PREFIX + email);
//        ValidateAssert.notNull(captchaCached, TipsConst.captcha_expire);
//        ValidateAssert.isTrue(captchaCached.equals(captcha), TipsConst.captcha_mismatching);
//        // 分布式锁定
//        final RLock lock = redissonClient.getLock(RedisKeyConst.MAIL_LOCK_PREFIX + email);
//        try {
//            boolean res = lock.tryLock();
//            if (!res) {
//                throw new ServiceException(BusinessState.DUPLICATE_REQUESTS);
//            }
//            try (HintManager hintManager = HintManager.getInstance()) {
//                hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_USER_SECURITY.toString());
//                UserEmail userEmail = userEmailMapper.selectByPrimaryKey(email);
//                ValidateAssert.notNull(userEmail, TipsConst.email_not_exists);
//                Duration duration = DateTimeUtil.between(userEmail.getCreatedTime(), DateTimeUtil.toMilli(LocalDateTime.now()));
//                MailRule.mailInUse(userEmail.getState(), duration.getSeconds(), CommonConst.expireTimeCaptcha);
//                this.resetPwd(userEmail.getUserId(), password);
//            } catch (Exception e) {
//                log.error("changePasswordByEmail email is {} e is {}", email, e, e);
//                throw new SystemException(TipsConst.password_change_failure);
//            }
//            redisTemplate.delete(RedisKeyConst.EMAIL_CAPTCHA_PREFIX + email);
//        } finally {
//            if (null != lock && lock.isLocked()) { // 是否还是锁定状态
//                if (lock.isHeldByCurrentThread()) {//是否是当前执行线程的锁
//                    lock.unlock(); // 释放锁
//                }
//            }
//        }
//    }
//
//    @Override
//    public UserPassword findUserPassword(Integer countryCallingCode, Long mobilePhoneNumber) {
//        Long userId = this.findUserId(countryCallingCode, mobilePhoneNumber);
//        return userPasswordMapper.selectByPrimaryKey(userId);
//    }
//
//    @Override
//    public Long findUserId(Integer countryCallingCode, Long mobilePhoneNumber) {
//        countryCallingCode = SmsRule.defaultCountryCallingCode(countryCallingCode);
//        UserMobilePhone phone = userMobilePhoneMapper.selectByState(countryCallingCode, mobilePhoneNumber,
//                Enums.UserMobilePhoneStateEnum.USED.code);
//        ValidateAssert.notNull(phone, TipsConst.mobile_phone_not_exists);
//        return phone.getUserId();
//    }
//
//    /**
//     * @opt 设置重置策略，一天只能重置一次类似这样。
//     * @param userId
//     * @return
//     */
//    @Override
//    public Enums.TargetEnum resetPassword(Long userId) {
//        UserInfo userInfo;
//        try (HintManager hintManager = HintManager.getInstance()) {
//            hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_USER.toString());
//            userInfo = userInfoMapper.selectByPrimaryKey(userId);
//            ValidateAssert.notNull(userInfo, TipsConst.user_not_exists);
//        }
//        if (userInfo.getMobilePhoneNumber() != 0L) {
//            this.resetPassword(userInfo.getCountryCallingCode(), userInfo.getMobilePhoneNumber());
//            return Enums.TargetEnum.MOBILE_PHONE;
//        } else if (StringUtils.isNoneBlank(userInfo.getEmail())) {
//            this.resetPassword(userInfo.getEmail());
//            return Enums.TargetEnum.EMAIL;
//        } else {
//            log.error("resetPassword userId {} userInfo data error", userId);
//            throw new ServiceException(BusinessState.UNKNOWN_ERROR);
//        }
//    }
//
//    /**
//     * 重置密码一定使用户在登录的时候才进行，但是为了功能的扩展，谁知道将来会被用到什么地方，所以，干脆校验写全
//     *
//     * @param email
//     */
//    @Override
//    public void resetPassword(String email) {
//        ValidateAssert.isTrue(StringExtendsUtils.isEmail(email), TipsConst.incorrect_email_format);
//        //当前时间戳
//        String password;
//        long userId;
//        try (HintManager hintManager = HintManager.getInstance()) {
//            hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_USER_SECURITY.toString());
//            UserEmail userEmail = userEmailMapper.selectByPrimaryKey(email);
//            ValidateAssert.notNull(userEmail, TipsConst.email_not_exists);
//            Duration duration = DateTimeUtil.between(userEmail.getCreatedTime(), DateTimeUtil.toMilli(LocalDateTime.now()));
//            MailRule.mailInUse(userEmail.getState(), duration.getSeconds(), DateTimeUtil.DAY);
//            this.resetPwd(userId = userEmail.getUserId(), password = PasswordUtil.randomPassword(passwordLength));
//        } catch (IllegalArgumentException e) {
//            throw e;
//        } catch (Exception e) {
//            log.error("重新设置账号密码失败 email is {}  e is {}", email, e, e);
//            throw new SystemException("重置失败");
//        }
//        // 发送成功邮件 这个需要计入一个记录 以便错误之后进行重新发送
//        // 也可以或者通过event的方式, bus总线。领域模型这种模式也是比较流行。
//        Context context = new Context();
//        context.setVariable("password", password);
//        String mail = templateEngine.process("retrieve_password_mail_template.html", context);
//        mailHelper.sendHtmlMail(email, "密码重置", mail);
//    }
//
//    @Override
//    public void resetPassword(Integer countryCallingCode, Long mobilePhoneNumber) {
//        ValidateAssert.isTrue(StringExtendsUtils.isMobilePhoneNumber(mobilePhoneNumber + ""), TipsConst.incorrect_mobile_phone_format);
//        countryCallingCode = SmsRule.defaultCountryCallingCode(countryCallingCode);
//        //当前时间戳
//        String password;
//        long userId;
//        try (HintManager hintManager = HintManager.getInstance()) {
//            hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_USER_SECURITY.toString());
//            UserMobilePhone phone = userMobilePhoneMapper.selectByState(countryCallingCode, mobilePhoneNumber,
//                    Enums.UserMobilePhoneStateEnum.USED.code);
//            // 未认证的时候不需要对时间进行校验
//            // 场景 1、未验证 一部手机，如果重置密码，那么已经跳过验证手机的界面或者验证未成功就点击重置密码
//            //     2、未验证 两部手机，那么一部手机没有点击验证，或者验证中途失败，这本身也是手机未注册
//            //     3、废弃 等同于未被注册
//            ValidateAssert.notNull(phone, TipsConst.mobile_phone_not_exists);
//            // 因为密码是摘要，无法逆运算，所以需要重新生成一次后更新
//            this.resetPwd(userId = phone.getUserId(), password = PasswordUtil.randomPassword(passwordLength));
//        } catch (IllegalArgumentException e) {
//            throw e;
//        } catch (Exception e) {
//            log.error("重新设置账号密码失败 phoneNumber is {}  e is {}", mobilePhoneNumber, e, e);
//            throw new SystemException("重置失败");
//        }
//        smsBo.sendPasswordResetSuccessSms(countryCallingCode, mobilePhoneNumber, password, passwordEncoder.encode(password));
//    }
//
//    private void resetPwd(Long userId, String password) {
//        UserPassword userPassword = userPasswordMapper.selectByPrimaryKey(userId);
//        userPassword.setPassword(passwordEncoder.encode(password));
//        userPassword.setModifiedTime(DateTimeUtil.toMilli(LocalDateTime.now()));
//        userPasswordMapper.updateByPrimaryKey(userPassword);
//    }
//
//    /**
//     * @opt
//     * 1、防止用户频繁输入短信验证码，需验证码发送限制。@todo
//     * 2、如果怕给db带来压力，可以设置限流或者熔断，但是千万不要加入
//     *         boolean f = redisTemplate.opsForValue().setIfAbsent(RedisKeyConst.PHONE_CAPTCHA_Obtain_LOCK_PREFIX + phoneNumber,
//     *                 1, 45, TimeUnit.SECONDS);
//     *         if(!f){
//     *             throw new ServiceException(BusinessState.DUPLICATE_REQUESTS);
//     *         }
//     * 因为如果加上之后系统挂了，用户请求另一个服务，会告知用户请点击，用户会认为系统很傻逼
//     * 3、查找手机看是否被注册，如果未被注册或者已被废弃，可以发送验证码
//     *   如果未注册完成，不能在这里实现完成，然后告诉用户，你已经成功注册。用户会懵B的。因为这里是验证码发送，不是注册
//     * @param mobilePhoneNumber
//     */
//    @Override
//    public void sendMobilePhoneRegisterCaptcha(Integer countryCallingCode, final Long mobilePhoneNumber) {
//        log.info("sendRegisterCaptcha param phoneNumber {}", mobilePhoneNumber);
//        smsBo.sendMobilePhoneCaptcha(SmsRule.defaultCountryCallingCode(countryCallingCode), mobilePhoneNumber,
//                CommonConst.expireTimeCaptcha, TimeUnit.SECONDS,
//                () -> {
//                    UserMobilePhone phone = userMobilePhoneMapper.selectByState(
//                            SmsRule.defaultCountryCallingCode(countryCallingCode),
//                            mobilePhoneNumber,
//                            Enums.UserMobilePhoneStateEnum.USED.code);
//                    log.info("sendRegisterCaptcha phoneNumber {} exists {}",
//                            mobilePhoneNumber, Objects.nonNull(phone));
//                    ValidateAssert.isTrue(Objects.isNull(phone), "手机已经被注册");
//                }
//        );
//    }
//
//    /**
//     * 注：查找手机账号和生成ID我是分开的.因为担心sharding和传统的获取连接池存在冲突（这个冲突可能未来的版本出现），为了消除不必要的风险，
//     * 将操作分成了两次sharding操作
//     * @param countryCallingCode
//     * @param mobilePhoneNumber
//     * @param captcha
//     */
//    @Override
//    public void verifyMobilePhoneRegisterCaptcha(Integer countryCallingCode, Long mobilePhoneNumber, Integer captcha) {
//        ValidateAssert.isTrue(StringExtendsUtils.isMobilePhoneNumber(mobilePhoneNumber + ""), TipsConst.incorrect_mobile_phone_format);
//        countryCallingCode = SmsRule.defaultCountryCallingCode(countryCallingCode);
//
//        ValidateAssert.notNull(captcha, "请输入验证码");
//        String lockKey = RedisKeyConst.PHONE_CAPTCHA_LOCK_PREFIX + mobilePhoneNumber;
//        final RLock lock = redissonClient.getLock(lockKey);
//        try {
//            boolean res = lock.tryLock();
//            if (!res) {
//                throw new ServiceException(BusinessState.DUPLICATE_REQUESTS);
//            }
//            // 校验验证码
//            smsBo.verifySmsCaptcha(countryCallingCode, mobilePhoneNumber, captcha,false);
//            // 查找手机账号
//            long nowTime = DateTimeUtil.toMilli(LocalDateTime.now());
//            UserMobilePhone phoneNotVerified;
//            try (HintManager hintManager = HintManager.getInstance()) {
//                hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_USER_SECURITY.toString());
//                List<UserMobilePhone> phoneList = userMobilePhoneMapper.selectByPhoneNumber(countryCallingCode, mobilePhoneNumber);
//                UserMobilePhone phoneInUse = Safes.of(phoneList).stream()
//                        .filter(p -> p.getState() == Enums.UserMobilePhoneStateEnum.USED.code)
//                        .findFirst().orElse(null);
//                ValidateAssert.isTrue(Objects.isNull(phoneInUse), TipsConst.mobile_phone_exists);
//                phoneNotVerified = Safes.of(phoneList).stream()
//                        .filter(p -> p.getState() == Enums.UserMobilePhoneStateEnum.NOT_VERIFIED.code)
//                        .findFirst().orElse(null);
//            }
//            // 根据手机账号的状态决定是否新增
//            Long userId = 0L, phoneId = 0L;
//            if (Objects.isNull(phoneNotVerified)) {
//                userId  = seqHelper.getSeqId(BusinessSeqEnum.USER.getBusinessName());
//                phoneId = seqHelper.getSeqId(BusinessSeqEnum.USER_MOBILE_PHONE.getBusinessName());
//            }
//            String password;
//            try (HintManager hintManager = HintManager.getInstance()) {
//                hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_USER_SECURITY.toString());
//                if (Objects.isNull(phoneNotVerified)) {
//                    // 因为要支持事务，否则只能另开一个类了。那样破坏了领域
//                    password = SpringContextHelper.getBean(UserBoBak.class).generatePhoneAndPassword(
//                            countryCallingCode, mobilePhoneNumber, phoneId, userId, nowTime);
//                } else {
//                    userId  = phoneNotVerified.getUserId();
//                    phoneId = phoneNotVerified.getId();
//                    this.resetPwd(userId, password = PasswordUtil.randomPassword(passwordLength));
//                }
//            }
//            // 生成用户信息
//            try (HintManager hintManager = HintManager.getInstance()) {
//                hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_USER.toString());
//                SpringContextHelper.getBean(UserBoBak.class)
//                        .generateUserInfor(null, countryCallingCode, mobilePhoneNumber, nowTime, userId);
//            } catch (Exception e) {
//                log.error("生成用户失败 phoneNumber  is {}  e is {}", mobilePhoneNumber, e, e);
//                throw new SystemException("生成手机账号失败");
//            }
//            // 更新账号状态为使用中
//            try (HintManager hintManager = HintManager.getInstance()) {
//                hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_USER_SECURITY.toString());
//                UserMobilePhone phone = userMobilePhoneMapper.selectById(phoneId, mobilePhoneNumber);
//                phone.setState(Enums.UserEmailStateEnum.USED.getCode());
//                userMobilePhoneMapper.updateStateById(phoneId, mobilePhoneNumber, Enums.UserMobilePhoneStateEnum.USED.code, nowTime);
//            } catch (Exception e) {
//                log.error("手机账号设置完成失败  phoneNumber is {}  e is {}", mobilePhoneNumber, e, e);
//                throw new SystemException("请重新提交");
//            }
//            smsBo.sendRegisterSuccessSms(countryCallingCode, mobilePhoneNumber, password, passwordEncoder.encode(password));
//        } finally {
//            if (null != lock && lock.isLocked()) { // 是否还是锁定状态
//                if (lock.isHeldByCurrentThread()) {//是否是当前执行线程的锁
//                    lock.unlock(); // 释放锁
//                }
//            }
//        }
//    }
//
//    @Override
//    public UserMergeInfoVo loginSuccessUserInfo(Long userId) {
//        UserInfo i = userInfoMapper.selectByPrimaryKey(userId);
//        assert Objects.nonNull(i);
//        UserSocialInfo si = userSocialInfoMapper.selectByPrimaryKey(userId);
//        return UserMergeInfoVo.builder()
//                .userId(userId).countryCallingCode(i.getCountryCallingCode()).mobilePhoneNumber(i.getMobilePhoneNumber())
//                .nickName(si.getNickName()).avatar(si.getAvatar()).bgImage(si.getBgImage())
//                .modifiedTime(i.getModifiedTime().compareTo(si.getModifiedTime()) > 0 ? i.getModifiedTime() : si.getModifiedTime())
//                .build();
//    }
//
//    @Transactional(rollbackFor = Exception.class)
//    public String generatePhoneAndPassword(Integer countryCallingCode, Long mobilePhoneNumber, Long phoneId, Long userId,
//                                           long nowTime) {
//        UserMobilePhone phone = UserMobilePhone.builder()
//                .id(phoneId)
//                .userId(userId)
//                .countryCallingCode(countryCallingCode)
//                .state(Enums.UserMobilePhoneStateEnum.NOT_VERIFIED.code)
//                .phoneNumber(mobilePhoneNumber)
//                .createdTime(nowTime)
//                .modifiedTime(nowTime)
//                .disuseTime(0L)
//                .build();
//        userMobilePhoneMapper.insert(phone);
//        String password = PasswordUtil.randomPassword(passwordLength);
//        String encryptedPassword = passwordEncoder.encode(password);
//        UserPassword userPassword = UserPassword.builder()
//                .userId(userId).password(encryptedPassword).createdTime(nowTime).modifiedTime(nowTime)
//                .build();
//        userPasswordMapper.insert(userPassword);
//        return password;
//    }
//
//    @Transactional(rollbackFor = Exception.class)
//    public void generateUserInfor(String email, Integer countryCallingCode, Long mobilePhoneNumber, long nowTime,
//                                  Long userId) {
//        // 查询用户是否存在，如果不存在再进行生成
//        UserInfo userInfo = userInfoMapper.selectByPrimaryKey(userId);
//        if (Objects.isNull(userInfo)) {
//            userInfo = UserInfo.builder()
//                    .userId(userId)
//                    .email(email)
//                    .countryCallingCode(countryCallingCode).mobilePhoneNumber(mobilePhoneNumber)
//                    .createTime(nowTime).modifiedTime(nowTime)
//                    .build();
//            userInfoMapper.insertSelective(userInfo);
//            UserSocialInfo userSocialInfo = UserSocialInfo.builder()
//                    .userId(userId).nickName(NickNameUtil.getName()).createTime(nowTime).modifiedTime(nowTime)
//                    .build();
//            userSocialInfoMapper.insertSelective(userSocialInfo);
//        }
//    }
//
//}
